//全局路径
var baseUrl = $("base").attr("href");
//浏览器类型
var $isIE = !!window.ActiveXObject || "ActiveXObject" in window;

// 公共对象选择器
$$selection = {
    gridTable: [], // 保存所有gridTable
    get: function (type, id) {
        var obj = null;
        this[type].forEach(function (item) {
            if (item.getId() === id) {
                obj = item;
                return false;
            }
        });
        return obj;
    },
    set: function (type, obj) {
        this[type].push(obj);
    }
};

// 为js里的Array对象添加方法
Array.prototype.remove = function (item) {
    var dx = this.indexOf(item);
    if (dx === -1) {
        return false;
    }
    this.removeIndex(dx);
};
Array.prototype.removeIndex = function (dx) {
    if (isNaN(dx) || dx > this.length) {
        return false;
    }
    this.splice(dx, 1);
};


/*===全局参数配置===*/
// 通知插件
toastr.options = {
    closeButton: false,
    debug: false,
    progressBar: false,
    positionClass: "toast-top-center toast-top-center-margin-top",
    onclick: null,
    showDuration: "300",
    hideDuration: "1000",
    timeOut: "1500",
    extendedTimeOut: "1000",
    showEasing: "swing",
    hideEasing: "linear",
    showMethod: "fadeIn",
    hideMethod: "fadeOut"
};
// grid表格样式
gridTableRowStyle = {
    select: "success",
    info: "info",
    edit: "warning",
    del: "danger"
};
// 表单验证默认配置
$.validator.setDefaults({
    debug: true,
    errorPlacement: function (error, element) {
        element.after(error);
        error.addClass("help-block");
        element.closest(".form-group").removeClass("has-success").addClass("has-error");
    },
    errorElement: "small",
    errorClass: "has-error",
    success: function (label) {
        label.closest(".form-group").removeClass("has-error").addClass("has-success");
        label.remove();
    }
});
jQuery.validator.addMethod("data-valid-decimal", function (value, element) {
    var Val = true;
    var arr = value.split(".");
    if (arr.length === 2) {
        if (arr[1].length > 2) {
            Val = false;
            return false;
        }
    }
    return Val;
}, "小数点后最多为两位");


//错误码
errorCode = {
    PATCHCA_MISTAKE: '1001',
    USERNAME_NOT_EXIST: '1002',
    PASSWORD_MISTAKE: '1003'
};


// 为jquery添加方法
$.extend({
    /**
     * 封装的ajax请求
     * @param url 请求地址
     * @param param 请求参数
     * @param successCallback 成功回调
     * @param errorCallback 失败回调
     */
    doAjax: function (url, param, successCallback, errorCallback) {
        if (typeof param === "function") {
            errorCallback = successCallback;
            successCallback = param;
            param = undefined;
        }

        var ajaxOption = {};
        ajaxOption.url = url;
        ajaxOption.type = "POST";
        if (param) {
            for (var k in param) {
                if (param.hasOwnProperty(k)) {
                    var value = param[k];
                    if (value === null || ("" + value).length === 0) {
                        delete param[k];
                    }
                }
            }
            ajaxOption.data = param;
        }
        ajaxOption.success = function (resp) {
            if (resp.code === "0") { // 调用成功
                if (successCallback) {
                    successCallback(resp.data);
                }
            } else { // 调用失败
                if (errorCallback) {
                    errorCallback(resp);
                } else {
                    $.error(resp.msg);
                }
            }
        };
        ajaxOption.error = function () {
            if (errorCallback) {
                errorCallback({code: "9999", msg: "通讯异常"});
            }
        };
        $.ajax(ajaxOption);
    },

    /**
     * 获取url地址参数
     */
    getUrlParams: function () {
        var url = window.location.href;
        var paramStr = url.split("?");
        var params = {};
        if (paramStr.length >= 2) {
            paramStr = paramStr[1];
            var arr = paramStr.split("&");
            arr.forEach(function (p) {
                var ps = p.split("=");
                params[ps[0]] = ps[1];
            });
        }
        return params;
    },

    /**
     * 重新加载分页
     * @param $dom 分页dom节点
     * @param pageInfo 分页信息
     * @param params 查询参数
     * @param reloadFunction 切换页面时调用的方法
     */
    reloadPageInfo: function ($dom, pageInfo, params, reloadFunction) {
        $dom = $($dom);

        // 生成分页dom节点
        var template = [];
        template.push("<ul class='pagination'>");
        template.push("  <li class='first'><a href='javascript:void(0)'>首页</a></li>");
        template.push("  <li class='pre'><a href='javascript:void(0)'>上一页</a></li>");
        template.push("  <li class='preGroup'><a href='javascript:void(0)'>...</a></li>");
        template.push("  <li class='nextGroup'><a href='javascript:void(0)'>...</a></li>");
        template.push("  <li class='next'><a href='javascript:void(0)'>下一页</a></li>");
        template.push("  <li class='last'><a href='javascript:void(0)'>尾页</a></li>");
        template.push("</ul>");
        var $pagination = $(template.join(""));

        // 添加页码
        pageInfo['navigatepageNums'].forEach(function (pageNum) {
            var $pageNum = $("<li><a href='javascript:void(0)'>" + pageNum + "</a></li>");
            $pageNum.attr("data-page-num", pageNum);
            if (pageNum === pageInfo['pageNum']) {
                $pageNum.addClass("active");
            }
            $pagination.find(".nextGroup").before($pageNum);
        });

        // 附加页码属性
        $pagination.find("li.first").attr("data-page-num", "1");
        $pagination.find("li.pre").attr("data-page-num", pageInfo['prePage']);
        $pagination.find("li.next").attr("data-page-num", pageInfo['nextPage']);
        $pagination.find("li.last").attr("data-page-num", pageInfo['pages']);

        if (pageInfo['pageNum'] === '1') {
            $pagination.find(".first").addClass("disabled");
        }
        if (pageInfo['pageNum'] === pageInfo['pages']) {
            $pagination.find(".last").addClass("disabled");
        }
        if (!pageInfo['hasPreviousPage']) {
            $pagination.find(".pre").addClass("disabled");
        }
        if (!pageInfo['hasNextPage']) {
            $pagination.find(".next").addClass("disabled");
        }
        if (pageInfo['firstPage'] === '1') {
            $pagination.find(".preGroup").addClass("hide");
        }
        if (pageInfo['lastPage'] === pageInfo['pages']) {
            $pagination.find(".nextGroup").addClass("hide");
        }

        $pagination.find("li[data-page-num]").on("click", function () {
            if ($(this).hasClass("disabled") || $(this).hasClass("active")) {
                return;
            }
            params['pageNum'] = $(this).attr("data-page-num");
            reloadFunction();
        });

        $dom.empty();
        $dom.append($pagination);
    },

    /**
     * 打开iframe弹出框
     * @param ele 弹出框的父级节点
     * @param opt 参数
     */
    openIframeDialog: function (ele, opt) {
        if (typeof ele !== "string") {
            opt = ele;
            ele = $("body", top.window.document);
        }
        return ele.openIframeDialog(opt);
    },

    rebindDataClick: function () {
        $("[data-click]").off("click").on("click", function () {
            var click = $(this).attr("data-click");
            eval(click);
        });
    },

    error: function (msg) {
        $.confirm({
            title: "错误",
            icon: "fa fa-warning",
            content: msg,
            theme: "material",
            type: "red",
            closeIcon: true,
            buttons: {
                ok: {
                    text: "确定",
                    btnClass: "btn-primary"
                }

            }
        });
    },
    success: function (msg) {
        toastr.success(msg);
    },

    /**
     * 将列表转成树型结构
     * @param list 要转成树的列表
     * @param idStr id字段
     * @param pidStr 父级id字段
     * @param childrenStr 子节点字段，可选，默认为children
     * @returns {Array} 树
     */
    listToTree: function (list, idStr, pidStr, childrenStr) {
        var tree = [], node = {}, parent;
        childrenStr = childrenStr || "children";
        for (var i = 0; i < list.length; i++) {
            node[list[i][idStr]] = list[i]; // 将列表转成对象
        }
        for (var j = 0; j < list.length; j++) {
            parent = node[list[j][pidStr]]; // 获取每个子对象的父对象
            if (parent) { // 父对象存在
                if (!parent[childrenStr]) {
                    parent[childrenStr] = [];
                }
                parent[childrenStr].push(list[j]);
            } else { // 父对象不存在
                tree.push(list[j]); // 放入第一层
            }
        }
        return tree;
    }
});
// 为jquery对象添加方法
$.fn.extend($.fn, {
    /**
     * 设置from表单中input,select等的值
     * @param value
     */
    setFormValue: function (value) {
        console.log(this, value);
    },

    /**
     * 将form表单序列化成json对象
     */
    serializeJson: function () {
        var arr = $(this).serializeArray();
        var json = {};
        arr.forEach(function (item) {
            json[item['name']] = item['value'];
        });
        // 处理select的值
        var selects = $(this).find("select");
        selects.each(function () {
            json[this.name] = this.value;
        });
        var decimals = $(this).find("[data-decimal]");
        decimals.each(function(){
            json[this.name] = Math.round((Number(this.value)) * 100);
        });
            return json;
    },

    /**
     * 打开包含iframe的弹出框
     * @param opt 参数，参数说明查看默认参数
     */
    openIframeDialog: function (opt) {
        var defaultWidth = 300;
        var defaultHeight = 400;
        // 默认参数
        var defaultOption = {
            title: "", // 弹出框标题
            url: null, // 内嵌iframe的url地址
            param: {}, // 额外的参数
            onOpen: null, // 打开弹出框时的回调
            onClose: null, // 关半弹出框时的回调
            beforeSubmit: null, // 表单提交前的回调，通过返回false来阻止表单提交
            afterSubmit: null, // 表单提交后的回调，通过返回false来阻止弹出框关闭
            resizable: true, // 是否允许调整窗口大小
            draggable: true, // 是否允许调整窗口位置
            width: null, // 设置窗口宽度，为null时会取子页面定义的窗口宽度，如果子页面也没有定义则取defaultWidth的值
            height: null, // 设置窗口高度，为null时会取子页面定义的窗口高度，如果子页面也没有定义则取defaultHeight的值
            minWidth: 200, // 设置最小窗口宽度
            minHeight: 150, // 设置最小窗口高度
            buttons: {
                ok: { // 确定按钮
                    text: "确定",
                    show: true,
                    style: "primary",
                    onclick: function () {
                        // 获取iframe页面form表单
                        var f = $("form", dialog.getSubPage())[0];
                        if (!formValidate(f)) { // 表单验证
                            console.log("验证失败");
                            return;
                        }


                        if (opt.beforeSubmit && opt.beforeSubmit(dialog, f) === false) {
                            return;
                        }

                        var params = $(f).serializeJson();

                        // 提交成功的回调函数
                        var scb = function (data) {
                            if (opt.afterSubmit && opt.afterSubmit(dialog, data) === false) {
                                return;
                            }
                            dialog.close();
                        };

                        // 提交失败的回调函数
                        var ecb = function (error) {
                            dialog.showError(error.msg);
                        };
                        $.doAjax(f.action, params, scb, ecb);
                    }

                },
                cancel: { // 取消按钮
                    text: "取消",
                    show: true,
                    style: "default",
                    onclick: function () {
                        dialog.close();
                    }
                },
                /*
                 * 增加的按钮，为一个数组，其中包含按钮对象，按钮对象的属性包括
                 * text：按钮的名称
                 * style：按钮的样式，default,primary,success,info,warning,danger
                 * onclick: 点击按钮的事件
                 */
                additional: []
            },
            afterLoad: function () { // 页面加载完成后的回调
                var doc = $iframe[0].contentWindow.document;
                $dialog.find(".modal-title").html(opt.title || $("title", doc).html());
                var f = $("form", dialog.getSubPage())[0];
                $(f).validate();
            }
        };
        opt = $.extend(true, {}, defaultOption, opt);

        var $dialog = $(IFRAME_DIALOG_TEMPLATE.join(""));
        $(this).append($dialog.show());
        opt.onOpen && opt.onOpen();

        var $dialogWindow = $dialog.find(".modal-dialog");
        $dialogWindow.height(opt.height || defaultHeight);
        $dialogWindow.width(opt.width || defaultWidth);
        $dialogWindow.css({
            minWidth: opt.minWidth + "px",
            minHeight: opt.minHeight + "px"
        });
        if (opt.resizable) { // 设置调整窗口大小
            $dialogWindow.resizable({
                autoHide: true, // 自动隐藏右下角三角符号,
                handles: "n, e, s, w, ne, se, sw, nw"

            });
        }
        if (opt.draggable) { // 设置拖拽
            $dialogWindow.draggable({
                handle: ".modal-header", // 设置只能拖拽标题栏
                opacity: 0.9, // 控制拖动时的透明度
                iframeFix: true // 防止拖动时选中iframe内部的内容
            });
        }

        // 处理按钮
        var $buttons = $dialog.find(".modal-footer");
        if (opt.buttons.ok.show) {
            var $ok = $("<button type='button' class='btn'></button>");
            $buttons.append($ok);
            $ok.html(opt.buttons.ok.text).addClass("btn-" + opt.buttons.ok.style).on("click", function () {
                opt.buttons.ok.onclick(dialog);
            });
        }
        if (opt.buttons.cancel.show) {
            var $cancel = $("<button type='button' class='btn'></button>");
            $buttons.append($cancel);
            $cancel.html(opt.buttons.cancel.text).addClass("btn-" + opt.buttons.cancel.style).on("click", function () {
                opt.buttons.cancel.onclick(dialog);
            });
        }
        if (opt.buttons.additional.length !== 0) {
            var $button = $("<button type='button' class='btn'></button>");
            $buttons.append($button);
            $button.html(opt.buttons.button.text).addClass("btn-" + opt.buttons.button.style).on("click", function () {
                opt.buttons.button.callback(dialog);
            });
        }


        // 加载中页面
        var showLoading = function () {
            $iframe.addClass("hide");
        };
        var hideLoading = function () {
            $iframe.removeClass("hide");
            $dialog.find(".loading").addClass("hide");
        };

        // 监听iframe页面加载完成事件
        var $iframe = $dialog.find("iframe");
        $iframe[0].onload = $iframe[0].onreadystatechange = function () {
            if (this.readyState && this.readyState !== 'complete') {
                // 兼容ie浏览器
            } else {
                var $body = $("body", dialog.getSubPage());
                var width = opt.width || $body.attr("data-width") || defaultWidth;
                var height = opt.height || $body.attr("data-height") || defaultHeight;
                $dialogWindow.width(width);
                $dialogWindow.height(height);
                hideLoading();
                // 加载完成后回调
                opt.afterLoad();
            }
        };

        // 关闭弹出框
        var closeDialog = function () {
            opt.onClose && opt.onClose();
            $dialog.remove();
        };
        var $close = $dialog.find(".modal-header button.close");
        $close.on("click", function () {
            closeDialog();
        });

        // 消息框
        var $msgContent = $dialog.find(".msg-content");
        var $msg = $msgContent.find(".msg");
        var showError = function (msg) {
            $msgContent.removeClass("hide");
            $msg.text(msg);
        };


        // 加载页面
        var iframeUrl = opt['url'];
        var urlParam = $.param(opt.param);
        iframeUrl += (urlParam.length === 0 ? "" : ("?" + urlParam));
        $dialog.find("iframe").attr("src", iframeUrl);
        showLoading();


        // 处理footer区，如果没有按钮则隐藏
        if ($buttons.children().length === 0) {
            $buttons.remove();
            $dialog.find(".modal-body").css("bottom", 0);
            $iframe.css("padding-bottom", 0);
        }


        var dialog = {
            close: closeDialog,
            getSubPage: function () {
                return $iframe[0].contentWindow.document;
            },
            showError: showError
        };
        return dialog;
    },

    /**
     * 生成数据表
     */
    gridTable: function (opt) {
        $(this).css("overflow", "auto");
        var gridTableId = $(this).attr("id");
        // 数据表默认参数
        var gridTableDefaultOption = {
            url: null, // 获取数据的url地址
            params: {}, // 获取数据时的额外参数
            columns: [], // 列信息
            idField: "id", // 主键的key名称
            showSerialNumber: true, // 是否显示序号
            showCheckbox: true, // 是否显示复选框
            showRadio: false, // 是否显示radio
            showControl: true, // 是否显示操作列
            multiSelect: true, // 是否可以多选
            autoSelect:false,//是否默认选中
            onClickRow: function (row, e) { // 行单击事件回调
                var target = e.target;
                if ($(target).closest("td.row-control").length !== 0) {
                    return true;
                }

                row.toggleSelect();
            },
            onDoubleClickRow: "info", // 行双击事件回调

            pageNum: '1', // 默认加载第几页
            pageSize: '10', // 每页多少行
            afterLoadData: null, // 表格数据加载完成后的回调
            getUrl: null, // 获取对象数据的接口地址
            infoUrl: null, // 查看详情的页面地址
            editUrl: null, // 修改的页面地址
            delUrl: null, // 删除操作的接口地址
            controls: {
                info: {
                    show: true,
                    url: null,
                    text: "查看详情",
                    onclick: function (row) {
                        row.showInfo();
                    }
                },
                edit: {
                    show: true,
                    url: null,
                    text: "修改",
                    onclick: function (row) {
                        row.showEdit();
                    }
                },
                del: {
                    show: true,
                    url: null,
                    text: "删除",
                    onclick: function (row) {
                        row.del();
                    }
                },
                additional: []
            }
        };
        // 列默认参数
        var columnDefaultOption = {
            title: "列名",
            field: null,
            dataType: "string",
            format: null,
            excelFormat: null,
            show: true, // 是否在页面显示
            export: true // 是否导出
        };
        var stringFormat = function (value) {
            if (value === undefined || value === null) {
                value = "";
            }
            return $("<span>" + value + "</span>");
        };
        var stringExcelFormat = function (value) {
            if (value === undefined || value === null) {
                value = "";
            }
            return value;
        };
        var decimalFormat = function (value) {
            if (value === undefined || value === null) {
                return $("<span></span>")
            }
            value = parseInt(value) / 100;
            value = value.toLocaleString();
            return $("<span class='text-warning'> ￥" + value + "</span>");
        };
        var decimalExcelFormat = function (value) {
            if (value === undefined || value === null) {
                return $("")
            }
            value = parseInt(value) / 100;
            value = value.toLocaleString();
            return "￥" + value;
        };
        var numberFormat = function (value) {
            if (value === undefined || value === null) {
                return $("<span></span>")
            }
            value = value.toLocaleString();
            return value;
        };
        opt = $.extend(true, {}, gridTableDefaultOption, opt);
        opt.controls.info.url = opt.controls.info.url || opt.infoUrl;
        opt.controls.edit.url = opt.controls.edit.url || opt.editUrl;
        opt.controls.del.url = opt.controls.del.url || opt.delUrl;

        // 全局属性
        var selectedRows = [];
        var hisSelectRows = [];
        var rows = [];
        var requestParam = {
            pageNum: opt.pageNum,
            pageSize: opt.pageSize
        };
        var gridTableData = null;
        // 生成表格
        var $table = $("<table class='table table-hover table-condensed table-responsive table-striped table-bordered'></table>");
        $(this).append($table);
        // 生成分页
        var $nav = $("<nav>");
        $(this).append($nav);

        // 生成表格内容
        var createTableContent = function () {
            // 生成表头
            var $thead = $("<tr class='table-head'></tr>");
            $table.append($("<thead>").append($thead));
            if (opt.showSerialNumber) {
                $thead.append("<th>#</th>");
            }
            if (opt.showCheckbox) {
                var $checkbox = $("<th><input type='checkbox' class='table_checkbox'></th>");
                $thead.append($checkbox);
                $checkbox.on("change", function () {
                    var isChecked = $checkbox.find("input[type=checkbox]")[0].checked;
                    selectedRows = [];
                    rows.forEach(function (row) {
                        if (isChecked) { // 全选
                            row.select();
                        } else {
                            row.unSelect();
                        }
                    });
                });

            }
            if (opt.showRadio) {
                $thead.append("<th><input type='radio'></th>");
            }
            opt.columns.forEach(function (column, dx) {
                opt.columns[dx] = column = $.extend({}, columnDefaultOption, column);
                if (column.show) {
                    $thead.append("<th>" + column.title + "</th>");
                    // opt.columns[dx] = column = $.extend({}, columnDefaultOption, column);
                    // $thead.append("<th>" + column.title + "</th>");

                    // 处理format(数据格式化)，如果定义了format方法则使用自定义的，如果没有定义则根据dataType选择格式化方法
                    if (!column.format) {
                        switch (column.dataType) {
                            case "string":
                                column.format = stringFormat;
                                break;
                            case "decimal":
                                column.format = decimalFormat;
                                break;
                            case "number":
                                column.format = numberFormat;
                                break;
                            default:
                                throw "列类型(dataType)错误：『" + column.dataType + "』无效";
                                break;
                        }
                    }
                    if (!column.excelFormat) {
                        switch (column.dataType) {
                            case "string":
                                column.excelFormat = stringExcelFormat;
                                break;
                            case "decimal":

                                column.excelFormat = decimalExcelFormat;
                                break;
                            case "number":
                                column.excelFormat = stringExcelFormat;// TODO
                                break;
                            default:
                                throw "列类型(dataType)错误：『" + column.dataType + "』无效";
                                break;
                        }
                    }
                }

            });
            if (opt.showControl) {
                $thead.append("<th>操作</th>");
            }
            if (!opt.autoSelect) {
                hisSelectRows = [];
            }
            loadData();
        };

        // 验证是否选中所有行
        var checkSelectAll = function () {
            if (opt.showCheckbox) {
                $table.find("tr.table-head input[type=checkbox]")[0].checked = (selectedRows.length === rows.length);
            }
        };

        // 生成行内容
        var createRow = function (rowData, dx) {
            var $tr = $("<tr>");
            if (opt.showSerialNumber) {
                $tr.append("<td class='row-index'>" + (dx + 1) + "</td>");
            }
            if (opt.showCheckbox) {
                $tr.append("<td class='row-checkbox'><input type='checkbox' class='table_checkbox'></td>");
            }
            if (opt.showRadio) {
                $tr.append("<td class='row-radio'><input type='radio'></td>");
            }
            opt.columns.forEach(function (column) {
                if (column.show) {
                    var cellData = rowData[column.field];
                    var $td = $("<td>");
                    $td.html(column.format(cellData, dx, rowData));
                    $tr.append($td);
                }
            });
            if (opt.showControl) {
                var $td = $("<td class='row-control'>");
                var $control = $(CONTROL_TEMPLATE.join(""));
                $td.append($control);
                $tr.append($td);

                var $info = $control.find("li.info");
                var $edit = $control.find("li.edit");
                var $del = $control.find("li.del");

                if (opt.controls.info.show) {
                    $info.children("a").html(opt.controls.info.text);
                    $info.on("click", function () {
                        opt.controls.info.onclick(row);
                    });
                } else {
                    $info.remove();
                }
                if (opt.controls.edit.show) {
                    $edit.children("a").html(opt.controls.edit.text);
                    $edit.on("click", function () {
                        opt.controls.edit.onclick(row);
                    });
                } else {
                    $edit.remove();
                }
                if (opt.controls.del.show) {
                    $del.children("a").html(opt.controls.del.text);
                    $del.on("click", function () {
                        opt.controls.del.onclick(row);
                    })
                } else {
                    $del.remove();
                }
                if (opt.controls.additional && opt.controls.additional.length > 0) {
                    opt.controls.additional.forEach(function (item) {
                        var $li = $("<li><a href='javascript:void(0)'></a></li>");
                        $li.children("a").html(item.text);
                        $li.on("click", function () {
                            item.onclick(row, gridTable);
                        });
                        $control.find("ul.dropdown-menu").append($li);
                    });
                }
            }

            // 定时器，防止双击时触发单击事件
            var _time = null;
            $tr.on({
                click: function (e) {
                    var target = e.target;
                    if ($(target).closest("td.row-control").length !== 0) {
                        return true;
                    }
                    clearTimeout(_time);
                    _time = setTimeout(function () {
                        opt.onClickRow && opt.onClickRow(row, e);
                    }, 300);
                },
                dblclick: function (e) {
                    var target = e.target;
                    if ($(target).closest("td.row-control").length !== 0) {
                        return true;
                    }
                    clearTimeout(_time);
                    var callback = opt.onDoubleClickRow;
                    if (typeof callback === "string") {
                        switch (callback) {
                            case "info":
                                row.showInfo();
                                break;
                            case "edit":
                                row.showEdit();
                                break;
                            default:
                                break;
                        }

                    } else if (typeof callback === "function") {
                        callback(row, e);
                    }
                }
            });

            var isSelected = false;
            var row = {
                getElement: function () {
                    return $tr;
                },
                isSelected: function () {
                    return isSelected;
                },
                select: function () {
                    isSelected = true;
                    if (opt.showCheckbox) {
                        $tr.find("td.row-checkbox>input[type=checkbox]")[0].checked = isSelected;
                    }
                    if (opt.showRadio) {
                        $tr.find("td.row-radio>input[type=radio]")[0].checked = isSelected;
                    }
                    this.setStyleSelect();
                    if (!opt.multiSelect) {
                        selectedRows.forEach(function (row) {
                            row.unSelect();
                        });
                    }
                    selectedRows.push(row);
                    if(opt.autoSelect){
                        var id = this.getData().id;
                        if (hisSelectRows.indexOf(id) === -1) {
                            hisSelectRows.push(id);
                        }
                        checkSelectAll();
                    }
                },
                unSelect: function () {
                    isSelected = false;
                    if (opt.showCheckbox) {
                        $tr.find("td.row-checkbox>input[type=checkbox]")[0].checked = isSelected;
                    }
                    if (opt.showRadio) {
                        $tr.find("td.row-radio>input[type=radio]")[0].checked = isSelected;
                    }
                    selectedRows.remove(row);
                    this.unsetStyleSelect();
                    checkSelectAll();
    
                    if(opt.autoSelect){
                        hisSelectRows.remove(row.getData().id);
                    }
                },
                toggleSelect: function () {
                    isSelected = !isSelected;
                    if (this.isSelected()) {
                        row.select();
                    } else {
                        row.unSelect();
                    }
                },
                getData: function () {
                    return rowData;
                },
                showInfo: function (title) {
                    var param = {};
                    param[opt.idField] = row.getData()[opt.idField];
                    $.openIframeDialog({
                        url: opt.controls.info.url,
                        param: param,
                        title: title,
                        onOpen: function () {
                            row.setStyleInfo();
                        },
                        onClose: function () {
                            row.unsetStyleInfo();
                        },
                        buttons: {
                            ok: {show: false},
                            cancel: {show: false}
                        }
                    });
                },
                showEdit: function (title) {
                    var param = {};
                    param[opt.idField] = row.getData()[opt.idField];

                    $.openIframeDialog({
                        url: opt.controls.edit.url,
                        param: param,
                        title: title,
                        onOpen: function () {
                            row.setStyleEdit();
                        },
                        onClose: function () {
                            row.unsetStyleEdit();
                        },
                        afterSubmit: function () {
                            $.success("修改成功");
                            gridTable.reloadData();
                        }
                    });
                },
                del: function () {
                    row.setStyleDel();
                    // 删除前确认
                    $.confirm({
                        title: "删除确认",
                        icon: "fa fa-question-circle-o",
                        content: "<p>确认删除该条数据吗？</p>",
                        theme: "modern",
                        type: "orange",
                        buttons: {
                            ok: {
                                text: "删除",
                                btnClass: "btn-danger",
                                action: function () {
                                    var param = {};
                                    param[opt.idField] = row.getData()[opt.idField];
                                    $.doAjax(opt.controls.del.url, param, function () {
                                        gridTable.reloadData();
                                        $.success("删除成功");
                                    }, function (error) {
                                        $.error(error.msg);
                                        row.unsetStyleDel();
                                    });
                                }
                            },
                            cancel: {
                                text: "取消",
                                btnClass: "btn-success",
                                action: function () {
                                    row.unsetStyleDel();
                                }
                            }
                        }
                    });
                },
                setStyle: function (style) {
                    $tr.addClass(style);
                },
                unsetStyle: function (style) {
                    $tr.removeClass(style);
                },
                setStyleSelect: function () {
                    this.setStyle(gridTableRowStyle.select);
                },
                unsetStyleSelect: function () {
                    this.unsetStyle(gridTableRowStyle.select);
                },
                setStyleInfo: function () {
                    this.setStyle(gridTableRowStyle.info);
                },
                unsetStyleInfo: function () {
                    this.unsetStyle(gridTableRowStyle.info);
                },
                setStyleEdit: function () {
                    this.setStyle(gridTableRowStyle.edit);
                },
                unsetStyleEdit: function () {
                    this.unsetStyle(gridTableRowStyle.edit);
                },
                setStyleDel: function () {
                    this.setStyle(gridTableRowStyle.del);
                },
                unsetStyleDel: function () {
                    this.unsetStyle(gridTableRowStyle.del);
                }
            };

            rows.push(row);

            return $tr;
        };

        // 加载数据
        var loadData = function () {
            // 获取表格数据
            $.doAjax(opt.url, $.extend({}, opt.params, requestParam), function (data) {
                recreateTable(data);
            }, function (error) {
                $.error(error.msg);
            });

        };

        // 根据数据重新生成表格
        var recreateTable = function(data) {
            gridTableData = data;
            var dataList = [];
            if (data['pageNum'] !== undefined && data['pageSize'] !== undefined) {
                if (Number(data['pageNum']) > Number(data['pages'])) {
                    requestParam.pageNum = data['pages'];
                    loadData();
                    return;
                }
                // 有分页
                var pageInfo = data;
                dataList = data['list'];
                var $pagination = $(PAGINATION_TEMPLATE.join(""));
                $nav.empty();
                $nav.append($pagination);
                // 添加页码
                pageInfo['navigatepageNums'].forEach(function (pageNum) {
                    var $pageNum = $("<li><a href='javascript:void(0)'>" + pageNum + "</a></li>");
                    $pageNum.attr("data-page-num", pageNum);
                    if (""+pageNum === pageInfo['pageNum']) {
                        $pageNum.addClass("active");
                    }
                    $pagination.find(".nextGroup").before($pageNum);
                });

                // 附加页码属性
                $pagination.find("li.first").attr("data-page-num", "1");
                $pagination.find("li.pre").attr("data-page-num", pageInfo['prePage']);
                $pagination.find("li.next").attr("data-page-num", pageInfo['nextPage']);
                $pagination.find("li.last").attr("data-page-num", pageInfo['pages']);

                if (pageInfo['pageNum'] === '1') {
                    $pagination.find(".first").addClass("disabled");
                }
                if (pageInfo['pageNum'] === pageInfo['pages']) {
                    $pagination.find(".last").addClass("disabled");
                }
                if (!pageInfo['hasPreviousPage']) {
                    $pagination.find(".pre").addClass("disabled");
                }
                if (!pageInfo['hasNextPage']) {
                    $pagination.find(".next").addClass("disabled");
                }
                if (pageInfo['firstPage'] === '1') {
                    $pagination.find(".preGroup").addClass("hide");
                }
                if (pageInfo['lastPage'] === pageInfo['pages']) {
                    $pagination.find(".nextGroup").addClass("hide");
                }

                $pagination.find("li[data-page-num]").on("click", function () {
                    if ($(this).hasClass("disabled") || $(this).hasClass("active")) {
                        return;
                    }
                    requestParam['pageNum'] = $(this).attr("data-page-num");

                    gridTable.reloadData();
                });


            } else {
                // 没有分页
                dataList = data;
            }

            dataList.forEach(function (item, dx) {
                var $row = createRow(item, dx);
                $table.append($row);
            });
            $.rebindDataClick();
            rows.forEach(function (row) {
                if (hisSelectRows.indexOf(row.getData().id) !== -1) {
                    row.select();
                }
            });
            opt.afterLoadData && opt.afterLoadData(rows, gridTable);
        };

        var init = function () {
            createTableContent();
        };
        init();

        // 数据表对象，用于封装常用数据及操作方法，返回给调用者使用
        var gridTable = {
            // 重载表格，包括表头
            refresh: function () {
                $table.empty();
                createTableContent();
            },
            // 重新加载表格数据
            reloadData: function (data) {
                $table.find("tr:not(.table-head)").remove();
                if (opt.showCheckbox) {
                    $table.find("tr.table-head input[type=checkbox]")[0].checked = false;
                }
                rows = []; // 清除掉之前保存的行数据
                selectedRows = []; // 清除掉保存的『已选择』行数据
                if (data !== null && data !== undefined) {
                    recreateTable(data);
                } else {
                    loadData();
                }
            },
            // 获取选中的行
            getSelectedRows: function () {
                return selectedRows;
            },
            getHisSelectedRows: function () {
                return hisSelectRows;
            },
            // 删除选中行
            delSelectedRows: function (option) {
                if (selectedRows.length === 0) {
                    $.error("未选择任何数据");
                    return;
                }
                if (!option.multiDelete && selectedRows.length > 1) {
                    $.error("每次只能删除一条数据");
                    return;
                }
                selectedRows.forEach(function (row) {
                    row.setStyleDel();
                });
                // 删除前确认
                $.confirm({
                    title: "删除确认",
                    icon: "fa fa-question-circle-o",
                    content: "<p>确认删除选中的 <span class='text-danger'>" + selectedRows.length + "</span> 条数据吗？</p>",
                    theme: "modern",
                    type: "orange",
                    buttons: {
                        ok: {
                            text: "删除",
                            btnClass: "btn-danger",
                            action: function () {
                                var arr = [];
                                selectedRows.forEach(function (row) {
                                    arr.push(row.getData()[opt.idField]);
                                    row.setStyleDel();
                                });
                                var delIdStr = arr.join(",");
                                var scb = function () {
                                    $.success("删除成功：删除了" + selectedRows.length + "条数据");
                                    gridTable.reloadData();
                                };
                                var ecb = function (error) {
                                    $.error(error.msg);
                                    selectedRows.forEach(function (row) {
                                        row.unsetStyleDel();
                                    });
                                };

                                var p = {};
                                if (option.multiDelete) {
                                    p['delIdStr'] = delIdStr;
                                } else {
                                    p[opt.idField] = delIdStr;
                                    option.url = opt.delUrl;
                                }
                                $.doAjax(option.url, p, scb, ecb);
                            }
                        },
                        cancel: {
                            text: "取消",
                            btnClass: "btn-success",
                            action: function () {
                                selectedRows.forEach(function (row) {
                                    row.unsetStyleDel();
                                });
                            }
                        }
                    }
                });
            },
            // 获取表格id
            getId: function () {
                return gridTableId;
            },
            // 获取请求参数
            getRequestParam: function () {
                return requestParam;
            },
            // 获取表格行
            getRows: function () {
                return rows;
            },
            // 下载excel
            download: function () {
                var option = {};
                option.datas = [];
                option.fileName = 'XXX数据表';
                var param = $.extend({}, opt.params, requestParam);
                param.pageSize = 2000000;
                $.doAjax(opt.url, param, function (data) {
                    var sheet = {
                        sheetName: 'sheet',
                        sheetHeader: [],
                        sheetFilter: [],
                        sheetData: []
                    };
                    var head = {};
                    opt.columns.forEach(function (column) {
                        sheet.sheetHeader.push(column.title);
                        sheet.sheetFilter.push(column.field);
                    });
                    option.datas.push(sheet);
                    data.list.forEach(function (item) {
                        var row = {};
                        opt.columns.forEach(function (column) {
                            var cell = item[column.field];
                            cell = column.excelFormat(cell);
                            row[column.field] = cell;
                        });
                        sheet.sheetData.push(row);
                    });
                    var toExcel = new ExportJsonExcel(option);
                    toExcel.saveExcel();
                }, function (error) {
                    console.log(error);
                    $.error(error.msg);
                });

            }
        };
        $$selection.set("gridTable", gridTable);
        return gridTable;
    }
});

// 页面控制，例如：控件渲染、格式化、焦点控制、屏蔽一些按键等
$(function () {
    // select下拉框数据加载
    $("select[data-url]").each(function (i, select) {
        var url = $(select).attr("data-url");
        var valueField = $(select).attr("data-value-field");
        var textField = $(select).attr("data-text-field");
        $.doAjax(url, function (list) {
            var defaultValue = $(select).attr("data-value");
            var options = [];
            list.forEach(function (item) {
                var value = item[valueField];
                var text = item[textField];
                var option = $("<option value='" + value + "'>" + text + "</option>");
                $(select).append(option);
                options.push(option);
            });
            if (defaultValue) {
                $(select).val(defaultValue);
                // options.forEach(function (option) {
                //     if (option.val() === defaultValue) {
                //         option[0].checked = true;
                //     }
                // });
            }
        });
    });
    // 按钮权限控制
    $(".grid-table .toolbar button[data-menu-id]").each(function () {
        var button = this;
        var menuId = $(this).attr("data-menu-id");
        $.doAjax("auth/hasPower", {menuId: menuId}, function (hasPower) {
            if (hasPower === "true") {
                $(button).show();
            }
        })
    });
    // 按钮事件绑定
    $.rebindDataClick();

    // 设置筛选框
    var $filter = $("form.filter");
    var filterWidth = $filter.attr("data-width") || 650;
    $filter.width(filterWidth);
    $filter.draggable({
        containment: "document"
    });

    // 自动获取并设置form表单或展示页面的值
    $("[data-auto-set-value]").each(function () {
        var container = this;
        var getUrl = $(container).attr("data-get-url");
        var type = $(container).attr("data-auto-set-value");
        var urlParam = $.getUrlParams();
        $.doAjax(getUrl, urlParam, function (data) {
            if (window.beforeAutoSetValue) {
                window.beforeAutoSetValue(data);
            }
            for (var key in data) {

                if (data.hasOwnProperty(key)) {
                    switch (type) {
                        case "edit":
                            var dom = $("[name=" + key + "]", container);
                            if (dom.length !== 0) {
                                if (dom.attr("data-decimal")) {
                                    dom.val((Number(data[key]))/100);
                                } else {
                                    dom.val(data[key]);
                                }
                                dom.attr("data-value", data[key]);
                            }
                            break;
                        case "info":
                            var dom = $("[data-field-name=" + key + "]", container);
                                if (dom.attr("data-decimal")) {
                                    dom.text("￥"+(Number(data[key]))/100);
                                } else {
                                    dom.text(data[key]);
                                }
                                dom.attr("data-value", data[key]);
                            break;
                        default:
                            break;
                    }
                }
            }
            if (window.afterAutoSetValue) {
                window.afterAutoSetValue(data);
            }
        }, function (error) {
            $.error(error.msg);
        })
    });
    
    $(".grid-table .filter").on("keypress", function (e) {
        if (e.charCode === 13) {
            $($(this).find("button")[1]).trigger("click");
        }
    });
});


/**
 * 添加公共方法
 * @param url 弹出层页面地址
 * @param gridId 列表编号
 * @param title 标题，默认为弹出页面的title
 * @param param 额外要传入到页面的参数（json对象的形式）
 */
function add(url, gridId, title, param) {
    $.openIframeDialog({
        title: title,
        url: url,
        param: param,
        afterSubmit: function () {
            var gridTable = $$selection.get("gridTable", gridId);
            gridTable.reloadData();
            $.success("添加成功");
        }
    });
}

/**
 * 修改公共方法
 * @param gridId grid表编号
 * @param title 标题，默认为弹出页面的title
 */
function edit(gridId, title) {
    var gridTable = $$selection.get("gridTable", gridId);
    var selectedRows = gridTable.getSelectedRows();
    if (selectedRows.length !== 1) {
        $.error("请选择<span class='text-danger'>一条</span>数据进行操作");
        return;
    }
    selectedRows[0].showEdit(title);
}

/**
 * 查看详情公共方法
 * @param gridId grid表编号
 * @param title 标题，默认为弹出页面的title
 */
function info(gridId, title) {
    var gridTable = $$selection.get("gridTable", gridId);
    var selectedRows = gridTable.getSelectedRows();
    if (selectedRows.length !== 1) {
        $.error("请选择<span class='text-danger'>一条</span>数据进行操作");
        return;
    }
    selectedRows[0].showInfo(title);
}

/**
 * 删除公共方法
 * @param gridId 列表编号
 * @param batchDelUrl 批量删除操作的接口地址
 * @param multiDelete boolean 是否允许批量删除，默认为true
 */
function del(gridId, batchDelUrl, multiDelete) {
    multiDelete = multiDelete !== false;
    var gridTable = $$selection.get("gridTable", gridId);
    gridTable.delSelectedRows({
        url: batchDelUrl,
        multiDelete: multiDelete
    });
}

/**
 * 刷新数据公共方法
 * @param gridId grid表格id
 */
function refresh(gridId) {
    var gridTable = $$selection.get("gridTable", gridId);
    gridTable.refresh();
}


/**
 * 下载公共方法
 * @param gridId
 */
function download(gridId) {
    var gridTable = $$selection.get("gridTable", gridId);
    gridTable.download();
}

/**
 * 切换展示/隐藏筛选
 */
function toggleFilter() {
    $(".grid-table .filter").toggleClass("show");
}

/**
 * 隐藏筛选
 */
function hideFilter() {
    $(".grid-table .filter").removeClass("show");
}

/**
 * 提交筛选
 */
function submitFilter(gridId) {
    var gridTable = $$selection.get("gridTable", gridId);


    var $filter = $(".grid-table .filter");
    var json = $filter.serializeJson();
    $.extend(gridTable.getRequestParam(), json);
    gridTable.reloadData();
    $filter.removeClass("show");
}

/**
 * 表单验证
 * @param f form表单
 * @returns {boolean}
 */
function formValidate(f) {
    return !!$(f).valid();
}


//==============页面模板

// iframe弹出框模板
const IFRAME_DIALOG_TEMPLATE = [];
IFRAME_DIALOG_TEMPLATE.push("<div class='modal'>");
IFRAME_DIALOG_TEMPLATE.push("  <div class='modal-dialog'>");
IFRAME_DIALOG_TEMPLATE.push("    <div class='modal-content'>");
IFRAME_DIALOG_TEMPLATE.push("      <div class='modal-header'>");
IFRAME_DIALOG_TEMPLATE.push("        <button type='button' class='close'>&times;</button>");
IFRAME_DIALOG_TEMPLATE.push("        <h4 class='modal-title'></h4>");
IFRAME_DIALOG_TEMPLATE.push("      </div>");
IFRAME_DIALOG_TEMPLATE.push("      <div class='modal-body'>");
IFRAME_DIALOG_TEMPLATE.push("        <iframe src></iframe>");
IFRAME_DIALOG_TEMPLATE.push("        <div class='msg-content text-danger text-center hide'><span class='fa fa-warning'></span>&nbsp;&nbsp;<span class='msg'></span></div>");
IFRAME_DIALOG_TEMPLATE.push("        <div class='draggable-mask'></div>");
IFRAME_DIALOG_TEMPLATE.push("        <div class='loading'><img src='img/loading-big.gif' alt='加载中。。。'></div>");
IFRAME_DIALOG_TEMPLATE.push("      </div>");
IFRAME_DIALOG_TEMPLATE.push("      <div class='modal-footer'></div>");
IFRAME_DIALOG_TEMPLATE.push("    </div>");
IFRAME_DIALOG_TEMPLATE.push("  </div>");
IFRAME_DIALOG_TEMPLATE.push("</div>");

// gridTable 操作按钮模板
const CONTROL_TEMPLATE = [];
CONTROL_TEMPLATE.push("<div class='dropdown'>");
CONTROL_TEMPLATE.push("    <a class='dropdown-toggle' type='button' data-toggle='dropdown'>");
CONTROL_TEMPLATE.push("        <i class='fa fa-gears'></i>");
CONTROL_TEMPLATE.push("        <span class='caret'></span>");
CONTROL_TEMPLATE.push("    </a>");
CONTROL_TEMPLATE.push("    <ul class='dropdown-menu dropdown-menu-right'>");
CONTROL_TEMPLATE.push("        <li class='info'><a href='javascript:void(0)'>查看详情</a></li>");
CONTROL_TEMPLATE.push("        <li class='edit'><a href='javascript:void(0)'>修改</a></li>");
CONTROL_TEMPLATE.push("        <li class='del'><a href='javascript:void(0)'>删除</a></li>");
CONTROL_TEMPLATE.push("    </ul>");
CONTROL_TEMPLATE.push("</div>");

// 分页模板
const PAGINATION_TEMPLATE = [];
PAGINATION_TEMPLATE.push("<ul class='pagination'>");
PAGINATION_TEMPLATE.push("  <li class='first'><a href='javascript:void(0)'>首页</a></li>");
PAGINATION_TEMPLATE.push("  <li class='pre'><a href='javascript:void(0)'>上一页</a></li>");
PAGINATION_TEMPLATE.push("  <li class='preGroup'><a href='javascript:void(0)'>...</a></li>");
PAGINATION_TEMPLATE.push("  <li class='nextGroup'><a href='javascript:void(0)'>...</a></li>");
PAGINATION_TEMPLATE.push("  <li class='next'><a href='javascript:void(0)'>下一页</a></li>");
PAGINATION_TEMPLATE.push("  <li class='last'><a href='javascript:void(0)'>尾页</a></li>");
PAGINATION_TEMPLATE.push("</ul>");

// 导出excel模板
const EXCEL_FILE = [];
EXCEL_FILE.push("<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>");
EXCEL_FILE.push("  <head>");
EXCEL_FILE.push("    <!--[if gte mso 9]>");
EXCEL_FILE.push("    <xml>");
EXCEL_FILE.push("      <x:ExcelWorkbook>");
EXCEL_FILE.push("        <x:ExcelWorksheets>");
EXCEL_FILE.push("          <x:ExcelWorksheet>");
EXCEL_FILE.push("            <x:Name>");
EXCEL_FILE.push("              {worksheet}");
EXCEL_FILE.push("            </x:Name>");
EXCEL_FILE.push("            <x:WorksheetOptions>");
EXCEL_FILE.push("              <x:DisplayGridlines/>");
EXCEL_FILE.push("            </x:WorksheetOptions>");
EXCEL_FILE.push("          </x:ExcelWorksheet>");
EXCEL_FILE.push("        </x:ExcelWorksheets>");
EXCEL_FILE.push("      </x:ExcelWorkbook>");
EXCEL_FILE.push("    </xml>");
EXCEL_FILE.push("    <![endif]-->");
EXCEL_FILE.push("  </head>");
EXCEL_FILE.push("  <body>");
EXCEL_FILE.push("    <table></table>");
EXCEL_FILE.push("  </body>");
EXCEL_FILE.push("</html>");
